package org.budo.support.lang.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

/**
 * @author lmw
 */
public class NumberUtil {
    private static final Logger log = Slf4j.getLogger();

    public static Boolean equals(Integer num1, Integer num2) {
        if (null == num1 || null == num2) {
            return false;
        }

        return num1.intValue() == num2.intValue();
    }

    public static List<Long> toLongList(String longArrayString) {
        if (StringUtil.isEmpty(longArrayString)) {
            return Collections.EMPTY_LIST;
        }

        if (longArrayString.startsWith("[") && longArrayString.endsWith("]")) {
            longArrayString = longArrayString.substring(1, longArrayString.length() - 1);
        }

        String[] stringArray = longArrayString.split(",");
        List<Long> longList = new ArrayList<Long>();
        for (int i = 0; i < stringArray.length; i++) {
            String value = stringArray[i];
            if (NumberUtil.isLong(value)) {
                longList.add(toLong(value));
            } else {
                log.error("#37 toIntegerArray error, intArrayString=" + longArrayString);
            }
        }
        return longList;
    }

    /**
     * 将逗号分隔的字符串转为Integer数组
     * 
     * @param integerArrayString
     */
    public static Integer[] toIntegerArray(String integerArrayString) {
        if (StringUtil.isEmpty(integerArrayString)) {
            return new Integer[0];
        }

        String[] stringArray = integerArrayString.split(",");
        Integer[] integerArray = new Integer[stringArray.length];
        for (int i = 0; i < stringArray.length; i++) {
            String value = stringArray[i];
            if (NumberUtil.isInteger(value)) {
                integerArray[i] = NumberUtil.toInteger(value);
            } else {
                log.error("#37 toIntegerArray error, intArrayString=" + integerArrayString);
            }
        }
        return integerArray;
    }

    public static Integer[] toIntegerArray(Object[] objectArray) {
        if (null == objectArray) {
            return null;
        }

        Integer[] integerArray = new Integer[objectArray.length];
        for (int i = 0; i < integerArray.length; i++) {
            Object value = objectArray[i];
            integerArray[i] = toInteger(value);
        }
        return integerArray;
    }

    public static boolean isInteger(Object value) {
        if (null == value) {
            return false;
        }

        try {
            Integer.parseInt(value.toString().trim());
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static boolean isDouble(Object value) {
        if (null == value) {
            return false;
        }

        try {
            Double.parseDouble(value.toString());
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 可以被转为long
     */
    public static boolean isLong(Object value) {
        if (null == value) {
            return false;
        }

        try {
            Long.parseLong(value.toString().trim());
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static Long toLong(Object value, Long defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return ((Number) value).longValue();
        }

        if (value instanceof String) {
            if (((String) value).isEmpty()) {
                return defaultValue;
            }

            return new Long(((String) value).trim());
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Long(new String((byte[]) value));
        }

        String message = "#97 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static Integer toInteger(Object value, Integer defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return ((Number) value).intValue();
        }

        if (value instanceof String) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new Integer((String) value);
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Integer(new String((byte[]) value));
        }

        String message = "#126 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static Double toDouble(Object value, Double defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        }

        if (value instanceof String) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new Double((String) value);
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Double(new String((byte[]) value));
        }

        String message = "#155 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static Short toShort(Object value, Short defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return new Short(((Number) value).shortValue());
        }

        if (value instanceof String) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new Short((String) value);
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Short(new String((byte[]) value));
        }

        String message = "#184 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static Float toFloat(Object value, Float defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return new Float(((Number) value).floatValue());
        }

        if (value instanceof String) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new Float((String) value);
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Float(new String((byte[]) value));
        }

        String message = "#213 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static Byte toByte(Object value, Byte defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof Number) {
            return new Byte(((Number) value).byteValue());
        }

        if (value instanceof String) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new Byte((String) value);
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new Byte(new String((byte[]) value));
        }

        String message = "#242 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof String || value instanceof Number) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new BigDecimal(value.toString());
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new BigDecimal(new String((byte[]) value));
        }

        String message = "#267 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        if (value instanceof String || value instanceof Number) {
            if (((String) value).trim().isEmpty()) {
                return defaultValue;
            }

            return new BigInteger(value.toString());
        }

        if (value instanceof byte[]) {
            if (((byte[]) value).length < 1) {
                return defaultValue;
            }

            return new BigInteger(new String((byte[]) value));
        }

        String message = "#292 must input number or string, value=" + value + ", type=" + value.getClass() + ", defaultValue=" + defaultValue;
        throw new IllegalArgumentException(message);
    }

    public static AtomicLong toAtomicLong(Object value, AtomicLong defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        Long longValue = toLong(defaultValue);
        return new AtomicLong(longValue);
    }

    public static AtomicInteger toAtomicInteger(Object value, AtomicInteger defaultValue) {
        if (null == value) {
            return defaultValue;
        }

        Integer integerValue = toInteger(value);
        return new AtomicInteger(integerValue);
    }

    public static Integer toInteger(Object value) {
        return toInteger(value, null);
    }

    public static Long toLong(Object value) {
        return toLong(value, null);
    }

    public static BigDecimal toBigDecimal(Object value) {
        return toBigDecimal(value, null);
    }

    public static Double toDouble(Object value) {
        return toDouble(value, null);
    }

    public static Short toShort(Object value) {
        return toShort(value, null);
    }

    public static Float toFloat(Object value) {
        return toFloat(value, null);
    }

    public static Byte toByte(Object value) {
        return toByte(value, null);
    }

    public static BigInteger toBigInteger(Object value) {
        return toBigInteger(value, null);
    }

    public static AtomicLong toAtomicLong(Object value) {
        return toAtomicLong(value, null);
    }

    public static AtomicInteger toAtomicInteger(Object value) {
        return toAtomicInteger(value, null);
    }

    /**
     * 将传入的值转换为指定类型
     * 
     * @param value
     * @param type
     * @return
     */
    public static <T extends Number> T toNumber(Object value, Class<T> type) {
        if (null == value || null == type || value.getClass().equals(type)) {
            return (T) value;
        }

        if (type.equals(Integer.class) || type.equals(int.class)) {
            return (T) toInteger(value);
        }

        if (type.equals(Long.class) || type.equals(long.class)) {
            return (T) toLong(value);
        }

        if (type.equals(Double.class) || type.equals(double.class)) {
            return (T) toDouble(value);
        }

        if (type.equals(Byte.class) || type.equals(byte.class)) {
            return (T) toByte(value);
        }

        if (type.equals(Float.class) || type.equals(float.class)) {
            return (T) toFloat(value);
        }

        if (type.equals(Short.class) || type.equals(short.class)) {
            return (T) toShort(value);
        }

        if (type.equals(BigDecimal.class)) {
            return (T) toBigDecimal(value);
        }

        if (type.equals(BigInteger.class)) {
            return (T) toBigInteger(value);
        }

        if (type.equals(AtomicInteger.class)) {
            return (T) toAtomicInteger(value);
        }

        if (type.equals(AtomicLong.class)) {
            return (T) toAtomicLong(value);
        }

        String message = "#399 value=" + value + ", value.type=" + (null == value ? null : value.getClass()) + ", type=" + type;
        throw new IllegalArgumentException(message);
    }

    /**
     * 判断是否全部小于指定值
     */
    public static Boolean allLessThan(Collection<Integer> values, Integer max) {
        if (null == values || null == max) {
            return null;
        }

        for (Integer each : values) {
            if (each >= max) {
                return false;
            }
        }

        return true;
    }
}
